package tp.pr2.mv;

public class Memory {
	private static final int MAXCELDAS = 100;
	private int contador;
	private CeldaMemoria[] memoria;// = null; //CeldaMemoria[] memoria = new CeldaMemoria[MAXCELDAS];
	
	
	public Memory() {
		this.memoria = new CeldaMemoria[MAXCELDAS];
		/* Se crean todas las MAXCELDAS CeldaMemoria apuntando a null, en el store según se
		necesita(Memoria va creciendo) vamos creando new CeldaMemoria. Quitamos inacialización de toda
		la memoria y solo se inicializa la primera celda. En el cuerpo del store se inializan nuevas
		celdas de memoria según se necesite */

		this.contador = 0;
	}
	
	public void nuevaCelda() {
		this.memoria[this.contador] = new CeldaMemoria();
		this.contador++;
	}
	
	public int getContador() {
		return this.contador;
	}
	
	public int getMemory(int pos) {
		int indice = busquedaLoad(pos);
		int contenido;
		if (indice == -1) contenido = -1;
		else contenido = this.memoria[indice].getMemCont();
		return contenido;
	}
	
	public CeldaMemoria getCelda(int x) {
		return this.memoria[x];
	}
	
	public void setCelda(int x, CeldaMemoria celda) {
		this.memoria[x] = celda;
	}
	
	public boolean memoriaLlena() {
		boolean llena = false;
		if (this.contador == MAXCELDAS)
			llena = true;
		return llena;
	}
	
	public boolean memoriaVacia() {
		boolean empty = false;
		if (this.contador == 0)
			empty = true;
		return empty;
	}
	
	public void setContadorDown() {
		this.contador--;
	}

	
	/* BÚSQUEDAS BINARIAS:
	 * Se precisan dos búsquedas binarias casi idénticas para load y para store.
	 * En el caso de load, necesitamos saber si el elemento no se ha encontrado (devolver -1).
	 * En el caso de store, necesitamos saber el elemento inmediatamente mayor al buscado, si no se
	 * ha encontrado este.
	 */
	
	public int busquedaStore(int xpos) {
		int inicio = 0;
		int fin = this.contador - 1;
		int posicionInsert=0;
		while (inicio <= fin) {
		     posicionInsert = (inicio+fin) / 2;
		     if ( this.memoria[posicionInsert].getMemPos() == xpos )
		    	 return posicionInsert;
		     else if ( this.memoria[posicionInsert].getMemPos() < xpos ) {
		    	inicio = posicionInsert+1;
		    	posicionInsert++;
		     }
		     else fin = posicionInsert-1; //posicionInsert--;
		}
		return posicionInsert;
	}
	
	public int busquedaLoad(int xpos) {
		int inicio = 0;
		int fin = this.contador - 1;
		int posicionInsert=0;
		boolean encontrado = false;
		while (inicio <= fin && !encontrado) {
		     posicionInsert = (inicio+fin) / 2;
		     if ( this.memoria[posicionInsert].getMemPos() == xpos )
		    	 encontrado = true;
		     else if ( this.memoria[posicionInsert].getMemPos() < xpos ) {
		    	inicio = posicionInsert+1;
		    	posicionInsert++;
		     }
		     else fin = posicionInsert-1; //posicionInsert--;
		}
		if (!encontrado) posicionInsert = -1; // Elemento no encontrado
		return posicionInsert;
	}

	public String toString(){
		String cadena=" ";
		if (this.contador == 0)
			cadena="<vacia>";
		else
			for (int i=0; i<this.contador; i++)
				cadena = cadena + this.memoria[i].toString();
		return cadena;
	}

	

}
